#include "RenderThread.h"
#include "QtThreadGraphics.h"

#include "Object.h"
#include "Gangster.h"
#include "Wall.h"
#include "Bullet.h"
#include "BlackHole.h"

#include <QtGui>
#include <iostream>
#include <sstream>
#include <QString>

using namespace std;

void RenderThread::run() {
    mutex.lock();
    int zoomX = getZoomX();
    int zoomY = getZoomY();

    int x = getZoomCenterX();
    int y = getZoomCenterY();

    bool zoomToPlayer__ = zoomToPlayer();
    Field* field = getField();
    Mob* player = field->getPlayer();
    QPainter* paint = getPainter();
    mutex.unlock();
    Object* o = 0;
    QString path;  // path to image, which it draws on render
    int rzX1 = 0, rzX2 = 0,  // rz - render zone,
        rzY1 = 0, rzY2 = 0;  // coordinates of zone,
                             // which is rendered
    int imageSizeX = 0, imageSizeY = 0;
    if( player == 0 ||  !zoomToPlayer__ ) {
        rzX1 = x;
        rzX2 = x;
        rzY1 = y;
        rzY2 = y;
    } else {
        rzX1 = player->getX();
        rzY1 = player->getY();
        rzX2 = player->getX();
        rzY2 = player->getY();
    }

    for( int i = zoomX / 2; i > 0 && rzX1 > 0; i-- ) {
        rzX1--;
    }
    for( int i = zoomX / 2; i > 0 && rzX2 < Field::WIDTH; i-- ) {
        rzX2++;
    }
    for( int i = zoomY / 2; i > 0 && rzY1 > 0; i-- ) {
        rzY1--;
    }
    for( int i = zoomY / 2; i > 0 && rzY2 < Field::HEIGHT; i-- ) {
        rzY2++;
    }

    imageSizeX = render.width()  / ( rzX2 - rzX1 );
    imageSizeY = render.height() / ( rzY2 - rzY1 );

    QImage background( ":/Wallpaper.jpg" );
    background = background.scaledToWidth(  render.width() );
    background = background.scaledToHeight( render.height() );
    paint->drawImage( 0, 0, background );

    int cX = 0, cY = 0;
    for( int i = rzX1; i < rzX2; i++ ) {
        cY = 0;
        for( int j = rzY1; j < rzY2; j++ ){
            mutex.lock();
            o = field->objectAt( i, j );
            mutex.unlock();
            path = whatToDraw( o );
            if( !path.isEmpty() ) {
                QImage image( path );
                image = image.scaled( imageSizeX, imageSizeY );
                paint->drawImage( cX * imageSizeX, cY * imageSizeY, image );
            }
            cY++;
        }
        cX++;
    }
}

QString RenderThread::whatToDraw( Object* o ) {
    if( o == 0 )                          return QString();
    if( o == f->getPlayer() )             return ":/Igrok.png";
    else switch( o->getSymbol() ) {
        case( Wall::WALLCHAR ):           return ":/Stena.png";     break;
        case( Gangster::GANGSTERCHAR ):
            switch( o->getTeam() ) {
                case( TEAMENUM ):         return ":/Soyuznik.png";  break;
                case( TEAMID ):           return ":/Protivnik.png"; break;
                case( TEAMDEMON ):        return ":/Demon.png";     break;
            }
            break;
        case( Bullet::BULLETCHAR ):       return ":/Pulya.png";     break;
        case( BlackHole::BLACKHOLECHAR ): return ":/Spauner.png";   break;
        default:                          return ":/SHIFTZ_LOGO.jpg";
    }
    return QString();
}

void RenderThread::paint( int zoomX, int zoomY, int zoomCenterX,
                          int zoomCenterY, bool zoomToPlayer, Field *f ) {
    mutex.lock();

    setZoomX( zoomX );
    setZoomY( zoomY );
    setZoomCenterX( zoomCenterX );
    setZoomCenterY( zoomCenterY );
    setZoomToPlayer( zoomToPlayer );
    setField( f );

    mutex.unlock();
    if( !isRunning() ) {
        start( LowPriority );
    } else {
        condition.wakeOne();
    }
}

void RenderThread::needsDrawing( GameWidget* widget,
                                 bool halluMode = false ) {
    wait();
    mutex.lock();

    QLabel* score = widget->getScore();
    QLabel* stats = widget->getStats();
    QLabel* map = widget->getMap();

    string str;
    QString displayed;
    Field* field = widget->getField();
    Mob* player = field->getPlayer();
    stringstream stream, stream2;
    QImage postEffectRender = render;

    mutex.unlock();

    if( player != 0 )  stream << "Lifes: " << player->getLifes()
                              << " Speed: "
                              << player->getMoveSpeed()
                              << " Shifts: " << player->getShifts()
                              << " " <<
                              "Level: " << player->getLevel();
    else stream << "Lifes: DEAD Speed: Dead don't move Shifts: How do you imagine this? Level: over 9000";
    str = stream.str();
    displayed = str.c_str();
    stats->setText( displayed );
    displayed.clear();
    str.clear();

    stream2 << "SCORE  GREEN DEATHS: " << field->getDeathsOfGreen()
            << " RED DEATHS: " << field->getDeathsOfRed()
            << " DEMON DEATHS: " << field->getDeathsOfDemons();
    str = stream2.str();
    displayed = str.c_str();
    score->setText( displayed );
    QPixmap pixmap;

    if( player && player->getLifes() == 1 ) {
        postEffectRender.setAlphaChannel( postEffectRender );
    }

    if( halluMode ) {
        postEffectRender.invertPixels();
    }

    pixmap.convertFromImage( postEffectRender );
    pixmap = pixmap.scaled( IMAGEWIDTH, IMAGEHEIGHT );

    map->setPixmap( pixmap );

    score->show();
    stats->show();
    map->show();
    widget->show();
}
